﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Unscrambler.Controls;
using Unscrambler.Constants;
using Unscrambler.ViewModels;
using System.Windows.Media.Animation;
using Unscrambler.Helpers;

namespace Unscrambler.Views
{
    /// <summary>
    /// Interaction logic for Gameboard.xaml
    /// </summary>
    public partial class Gameboard : UserControl, IGameboardView
    {
                        
        public static readonly DependencyProperty WordProperty = DependencyProperty.Register(
            "Word", typeof(string), typeof(Gameboard), 
            new PropertyMetadata(string.Empty, new PropertyChangedCallback(Gameboard.OnCurrentWordChanged)),
            null);

        
        private static void OnCurrentWordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Gameboard gameboard = d as Gameboard;
            if (gameboard != null)
            {
                gameboard.ResetBoard();
                string word = e.NewValue as string;
                TilePositioner tilePositioner = new TilePositioner(gameboard);
                tilePositioner.PositionAllTiles(word);
            }
        }

        #region IGameboardView members
        public string Word
        {
            get { return (string)this.GetValue(WordProperty); }
            set
            {
                this.SetValue(WordProperty, value);
            }
        }

        public AnswerCanvas AnswerPanel
        {
            get { return this.answerCanvas; }
        }

        public Panel ScramblePanel
        {
            get { return this.scrambleCanvas; }
        }
           
        public void ResetBoard()
        {
            this.scrambleCanvas.Children.Clear();
            this.scrambleCanvas.Children.Add(this.answerCanvas);
            this.answerCanvas.Children.Clear();
            this.answerCanvas.UpdateAnswer();
        }

        public void UpdateAnswer(UIElement element)
        {
            PutTileInDifferentCanvasIfNecessary(element);
            this.answerCanvas.UpdateAnswer();
            GiveAnswerStateToViewModel();
        }
                
        
        #endregion

        private void PutTileInDifferentCanvasIfNecessary(UIElement itemManipulated)
        {
            if (WasTileMovedIntoTheAnswerCanvas(itemManipulated))
            {
                this.ScramblePanel.Children.Remove(itemManipulated);
                this.AnswerPanel.Children.Add(itemManipulated);
            }
            else if (WasTileMovedOutOfTheAnswerCanvas(itemManipulated))
            {
                this.AnswerPanel.Children.Remove(itemManipulated);
                this.ScramblePanel.Children.Add(itemManipulated);
            }
        }

        private bool WasTileMovedIntoTheAnswerCanvas(UIElement itemManipulated)
        {
            return new Rect(this.AnswerPanel.RenderSize).Contains(itemManipulated.RenderTransform.TransformBounds(new Rect(itemManipulated.RenderSize)))
                && !this.AnswerPanel.Children.Contains(itemManipulated);
        }

        private bool WasTileMovedOutOfTheAnswerCanvas(UIElement itemManipulated)
        {
            return !new Rect(this.AnswerPanel.RenderSize).Contains(itemManipulated.RenderTransform.TransformBounds(new Rect(itemManipulated.RenderSize)))
                && this.AnswerPanel.Children.Contains(itemManipulated);
        }

        private void GiveAnswerStateToViewModel()
        {
            GameboardViewModel viewModel = this.DataContext as GameboardViewModel;
            if (viewModel != null)
            {
                if (this.answerCanvas.IsCorrect)
                {
                    viewModel.IsCurrentWordCorrect = true;
                }
                else
                {
                    viewModel.IsCurrentWordCorrect = false;
                };
                CommandManager.InvalidateRequerySuggested();
                
            }
        }

        public Gameboard()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Gameboard_Loaded);
            
            TileManipulator tileManipulator = new TileManipulator(this);
            tileManipulator.HandleTileManipulation();
            
        }

        void Gameboard_Loaded(object sender, RoutedEventArgs e)
        {
            //hack because it was the only way I could find to correctly set the height of the scramble canvas
            //to fill the alotted space without going offscreen.
            this.Loaded -= new RoutedEventHandler(Gameboard_Loaded);
            this.scrambleCanvas.Height = this.ActualHeight - this.infoRow.ActualHeight;
        }
    }
}
